/**
 * 
 */
package org.jinion.test.dao;

import java.sql.SQLException;
import java.util.Iterator;
import java.util.Map;

import org.jinion.database.AbstractDatabase;
import org.jinion.database.DatabaseFactory;
import org.jinion.database.model.AbstractResult;
import org.jinion.database.model.impl.TableRow;
import org.jinion.test.model.Account;
import org.jinion.test.model.Transfer;
import org.jinion.util.BeanMap;

/**
 * @author zhlmmc
 *
 */
public class TransferDAO {
	private AbstractDatabase myDatabase;
	private AccountDAO accountDAO;
	
	public TransferDAO(AccountDAO accountDAO) throws DAOException{
		try {
			myDatabase = DatabaseFactory.getDatabase();
		} catch (Exception e) {
			throw new DAOException(e);
		} 
		this.accountDAO = accountDAO;
	}
	
	public void createTransfer(Transfer transfer) throws DAOException{
		Account fromAccount = transfer.getFromAccount();
		Account toAccount = transfer.getToAccount();
		
		Long blance1 = fromAccount.getBalance();
		Long blance2 = toAccount.getBalance();
		blance1 -= 500;
		blance2 += 500;
		fromAccount.setBalance(blance1);
		toAccount.setBalance(blance2);
		
		Map map = new BeanMap(transfer);
		// BeanMap can not handle foreign key (reference to other bean). 
		// The values of "fromAccount" and "toAccount" in the map are wrong.
		// We have to fix them manually.
		map.put("fromAccount", transfer.getFromAccount().getAccountNumber());
		map.put("toAccount", transfer.getToAccount().getAccountNumber());
		try {
			myDatabase.beginTransaction();
			
			AbstractResult result = myDatabase.insert("transfer", map);
			Object key = result.getFirstGeneratedKey();
			if (key != null) {
				transfer.setTransferId((Integer)key);
			}
			else{
				myDatabase.rollback();
				throw new DAOException("Can not get generated primary key.");
			}
			accountDAO.updateAccount(fromAccount);
			accountDAO.updateAccount(toAccount);
			
			myDatabase.commitTransaction();
		} catch (SQLException e) {
			try {
				myDatabase.rollback();
			} catch (SQLException e1) {
				e.setNextException(e1);
			}
			
			throw new DAOException(e);
		}
	}
	
	public Transfer[] getTransfers(Account account) throws DAOException{
		myDatabase.where("fromAccount", account.getAccountNumber());
		myDatabase.orWhere("toAccount", account.getAccountNumber());
		
		try {
			AbstractResult result = myDatabase.query("transfer");
			Transfer[] transfers = new Transfer[result.size()];
			int index = 0;
			for (Iterator iterator = result.getTable().getRows().iterator(); iterator.hasNext();) {
				TableRow row = (TableRow) iterator.next();
				transfers[index] = new Transfer();
				BeanMap map = new BeanMap(row.getMap());
				map.fillBean(transfers[index]);
				// BeanMap can not handle foreign key (reference to other bean). 
				// The property "fromAccount" and "toAccount" are not set.
				// We have to set the properties manually.
				transfers[index].setFromAccount(accountDAO.getAccount(row.getString("fromAccount")));
				transfers[index].setToAccount(accountDAO.getAccount(row.getString("toAccount")));
				
				index++;
			}
			
			return transfers;
		} catch (SQLException e) {
			throw new DAOException(e);
		}
	}
	
	/**
	 * Just for test convenient.
	 */
	public void deleteAll() throws DAOException{
		try {
			myDatabase.delete("transfer");
		} catch (SQLException e) {
			throw new DAOException(e);
		}
	}
}
